/*     */ package com.zimbra.cs.util;
/*     */ 
/*     */ import com.google.common.annotations.VisibleForTesting;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import java.io.BufferedOutputStream;
/*     */ import java.io.File;
/*     */ import java.io.FileInputStream;
/*     */ import java.io.FileOutputStream;
/*     */ import java.io.IOException;
/*     */ import java.io.ObjectInputStream;
/*     */ import java.io.ObjectOutputStream;
/*     */ import java.io.Serializable;
/*     */ import java.util.ArrayList;
/*     */ import java.util.ConcurrentModificationException;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.NoSuchElementException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class SpoolingCache<K extends Serializable>
/*     */   implements Iterable<K>
/*     */ {
/*     */   final int memlimit;
/*     */   final List<K> memcache;
/*  40 */   File diskcache = null;
/*  41 */   private ObjectOutputStream oos = null;
/*  42 */   int size = 0;
/*  43 */   final List<SpoolingCache<K>.CacheIterator> iterators = new ArrayList(3);
/*     */   private static final int DEFAULT_MEMORY_CACHE_ITEMS = 100000;
/*     */   
/*     */   public SpoolingCache()
/*     */   {
/*  48 */     this(100000);
/*     */   }
/*     */   
/*     */   public SpoolingCache(int memoryItemLimit) {
/*  52 */     this.memlimit = memoryItemLimit;
/*  53 */     this.memcache = new ArrayList(Math.min(this.memlimit, 1000));
/*     */   }
/*     */   
/*     */   public void add(K item) throws IOException {
/*  57 */     if (this.memcache.size() < this.memlimit) {
/*  58 */       this.memcache.add(item);
/*     */     } else {
/*  60 */       if (this.oos == null) {
/*  61 */         this.diskcache = File.createTempFile("scache", ".tmp", new File(LC.zimbra_tmp_directory.value()));
/*  62 */         this.oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(this.diskcache)));
/*     */       }
/*  64 */       this.oos.writeObject(item);
/*     */     }
/*  66 */     this.size += 1;
/*     */   }
/*     */   
/*     */   public void cleanup() {
/*  70 */     this.size = 0;
/*  71 */     this.memcache.clear();
/*  72 */     if (this.oos != null) {
/*  73 */       ByteUtil.closeStream(this.oos);
/*  74 */       this.oos = null;
/*     */     }
/*  76 */     if (this.diskcache != null) {
/*  77 */       this.diskcache.delete();
/*  78 */       this.diskcache = null;
/*     */     }
/*  80 */     if (!this.iterators.isEmpty()) {
/*  81 */       for (SpoolingCache<K>.CacheIterator it : new ArrayList(this.iterators)) {
/*  82 */         it.cleanup();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private class CacheIterator implements Iterator<K> {
/*  88 */     private final int oldsize = SpoolingCache.this.size;
/*  89 */     private int index = 0;
/*  90 */     private ObjectInputStream ois = null;
/*     */     
/*     */ 
/*     */     CacheIterator() {}
/*     */     
/*     */     public K next()
/*     */     {
/*  97 */       if (!hasNext())
/*  98 */         throw new NoSuchElementException();
/*  99 */       if (this.index < SpoolingCache.this.memlimit) {
/* 100 */         return (Serializable)SpoolingCache.this.memcache.get(this.index++);
/*     */       }
/*     */       try {
/* 103 */         if (this.ois == null) {
/* 104 */           this.ois = new ObjectInputStream(new FileInputStream(SpoolingCache.this.diskcache));
/*     */         }
/* 106 */         K item = (Serializable)this.ois.readObject();
/* 107 */         this.index += 1;
/* 108 */         return item;
/*     */       } catch (IOException e) {
/* 110 */         throw (SpoolingCache.this.diskcache == null ? new ConcurrentModificationException() : new RuntimeException("error reading from spool file"));
/*     */       } catch (ClassNotFoundException e) {
/* 112 */         throw new RuntimeException("could not deserialize spooled item");
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */     public boolean hasNext()
/*     */     {
/* 119 */       checkForComodification();
/*     */       
/* 121 */       if (this.index < SpoolingCache.this.size) {
/* 122 */         return true;
/*     */       }
/* 124 */       cleanup();
/* 125 */       return false;
/*     */     }
/*     */     
/*     */ 
/*     */     public void remove()
/*     */     {
/* 131 */       throw new UnsupportedOperationException();
/*     */     }
/*     */     
/*     */     final void checkForComodification() {
/* 135 */       if (SpoolingCache.this.size != this.oldsize) {
/* 136 */         throw new ConcurrentModificationException();
/*     */       }
/*     */     }
/*     */     
/*     */     void cleanup() {
/* 141 */       if (this.ois != null) {
/* 142 */         ByteUtil.closeStream(this.ois);
/* 143 */         this.ois = null;
/*     */       }
/* 145 */       synchronized (SpoolingCache.this.iterators) {
/* 146 */         SpoolingCache.this.iterators.remove(this);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public Iterator<K> iterator()
/*     */   {
/* 153 */     if (this.oos != null) {
/*     */       try {
/* 155 */         this.oos.flush();
/*     */       } catch (IOException e) {
/* 157 */         throw new RuntimeException("could not flush pending spool writes");
/*     */       }
/*     */     }
/*     */     
/* 161 */     SpoolingCache<K>.CacheIterator it = new CacheIterator();
/* 162 */     synchronized (this.iterators) {
/* 163 */       this.iterators.add(it);
/*     */     }
/* 165 */     return it;
/*     */   }
/*     */   
/*     */   public int size() {
/* 169 */     return this.size;
/*     */   }
/*     */   
/*     */   @VisibleForTesting
/*     */   boolean isSpooled() {
/* 174 */     return this.diskcache != null;
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/util/SpoolingCache.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */